#include <unistd.h>
#include <stdio.h>
// #include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

/* cpu使用率核心数据信息结构体定义 */
struct my_cpu {
    uint64_t user;       /* 用户态CPU时间 */
    uint64_t nice;       /* 低优先级用户态CPU时间 */
    uint64_t system;     /* 内核态CPU时间 */
    uint64_t idle;       /* 空闲CPU时间 */
    uint64_t iowait;     /* 等待I/O操作CPU时间 */
    uint64_t irq;        /* 硬中断CPU时间 */
    uint64_t softirq;    /* 软中断CPU时间 */
    uint64_t steal;      /* 虚拟机CPU时间 */
    uint64_t guest;      /* 虚拟机低优先级CPU时间 */
    uint64_t guest_nice; /* 虚拟机低优先级用户态CPU时间 */
};

struct my_cpu2 {
    uint32_t user;       /* 用户态CPU时间 */
    uint32_t nice;       /* 低优先级用户态CPU时间 */
    uint32_t system;     /* 内核态CPU时间 */
    uint32_t idle;       /* 空闲CPU时间 */
    uint32_t iowait;     /* 等待I/O操作CPU时间 */
    uint32_t irq;        /* 硬中断CPU时间 */
    uint32_t softirq;    /* 软中断CPU时间 */
    uint32_t steal;      /* 虚拟机CPU时间 */
    uint32_t guest;      /* 虚拟机低优先级CPU时间 */
    uint32_t guest_nice; /* 虚拟机低优先级用户态CPU时间 */
};

#define MY_CPU_FSCANF(fp, buf, cpu)                                                        \
    fscanf(fp, "%16s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", buf, &((cpu)->user),        \
        &((cpu)->nice), &((cpu)->system), &((cpu)->idle), &((cpu)->iowait), &((cpu)->irq), \
        &((cpu)->softirq), &((cpu)->steal), &((cpu)->guest), &((cpu)->guest_nice))

#define MY_CPU_FSCANF2(fp, buf, cpu)                                                        \
    fscanf(fp, "%s %u %u %u %u %u %u %u %u %u %u", buf, &((cpu)->user),        \
        &((cpu)->nice), &((cpu)->system), &((cpu)->idle), &((cpu)->iowait), &((cpu)->irq), \
        &((cpu)->softirq), &((cpu)->steal), &((cpu)->guest), &((cpu)->guest_nice))

int main() {
    FILE         *fp;
    int       ret, i;
    struct my_cpu2 cpu_info[5], cpu_info_old[5];
    char          buf[16 + 1];

    #ifdef __x86_64__
        printf("Compiled for 64-bit x86_64 architecture\n");
    #elif defined(__i386__)
        printf("Compiled for 32-bit x86 architecture\n");
    #elif defined(__aarch64__)
        printf("Compiled for 64-bit ARM64 (aarch64) architecture\n");
    #elif defined(_WIN64)
        printf("Compiled for 64-bit Windows\n");
    #elif defined(__arm__) && !defined(__aarch64__)
        printf("Compiled for 32-bit ARM architecture\n");
    #else
        printf("Unknown architecture\n");
    #endif
    
    printf("void * = %d\nuint64_t = %d\n", sizeof(void *), sizeof(uint64_t));
    /* 打开全局cpu状态信息虚拟文件 */
    fp = fopen("/proc/stat", "r");
    if (fp == NULL) {
        // printf("Open /proc/stat file error, %s(%d)\n", strerror(errno), errno);
        return -1;
    }

    while (1) {
        uint64_t ou,oa,nu,na;
        /* 先读取一次原始数据, 然后后续连续间隔指定时间获取数据, 并实时输出使用率 */
        for (i = 0; i < 5; i++) {
            ret = MY_CPU_FSCANF2(fp, buf, &cpu_info_old[i]);
            if (ret != 11) {
                printf("ret = %d\n", ret);
                return -1;
            } else {
                // printf("%s\t%u\t%u\t%u\t%u\t%u\n", buf, cpu_info_old[i].user, cpu_info_old[i].nice, cpu_info_old[i].system, cpu_info_old[i].idle, cpu_info_old[i].iowait);
                // printf("%s\t%u\t%u\t%u\t%u\t%u\n", buf, cpu_info_old[i].irq, cpu_info_old[i].softirq, cpu_info_old[i].steal, cpu_info_old[i].guest, cpu_info_old[i].guest_nice);
                
            }
            
        }
        // printf("\n");
        sleep(1);
        fflush(fp);
        if (fseek(fp, 0, SEEK_SET) != 0) {
            // printf("Seek /proc/stat file error, %s(%d)\n", strerror(errno), errno);
            printf("fseek fail\n");
            return -1;
        }
        for (i = 0; i < 5; i++) {
            ret = MY_CPU_FSCANF2(fp, buf, &cpu_info[i]);
            if (ret != 11) {
                printf("ret = %d\n", ret);
                return -1;
            } else {
                // printf("%s\t%u\t%u\t%u\t%u\t%u\n", buf, cpu_info[i].user, cpu_info[i].nice, cpu_info[i].system, cpu_info[i].idle, cpu_info[i].iowait);
                // printf("%s\t%u\t%u\t%u\t%u\t%u\n", buf, cpu_info[i].irq, cpu_info[i].softirq, cpu_info[i].steal, cpu_info[i].guest, cpu_info[i].guest_nice);
                ou = cpu_info_old[i].user + cpu_info_old[i].system + cpu_info_old[i].nice;
                oa = ou + cpu_info_old[i].idle + cpu_info_old[i].iowait;
                nu = cpu_info[i].user + cpu_info[i].system + cpu_info[i].nice;
                na = nu + cpu_info[i].idle + cpu_info[i].iowait;
                printf("%s usage : %1.2f%%\n", buf, (float)(nu-ou)*100/(na-oa));
            }
            
        }
        printf("\n");
        sleep(1);
        fflush(fp);
        if (fseek(fp, 0, SEEK_SET) != 0) {
            // printf("Seek /proc/stat file error, %s(%d)\n", strerror(errno), errno);
            printf("fseek fail\n");
            return -1;
        }
    }
    fclose(fp);

    return 0;
}
